﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace SECSendEmailService
{
    public class ImpersonationService
    {

        #region Consts

        public const int LOGON32_LOGON_INTERACTIVE = 2;
        public const int LOGON32_PROVIDER_DEFAULT = 0;

        #endregion Consts

        #region External API
        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern int LogonUser(
            string lpszUsername, string lpszDomain,
            string lpszPassword, int dwLogonType,
            int dwLogonProvider, out IntPtr phToken
            );

        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool RevertToSelf();

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern int CloseHandle(IntPtr hObject);

        #endregion External API

        #region Methods
        //执行实施工作
        public void PerformImpersonatedTask(string username, string domain,
            string password, int logonType, int logonProvider, Action methodToPerform)
        {
            IntPtr token = IntPtr.Zero;
            if (RevertToSelf())
            {
                if (LogonUser(username, domain, password, logonType,
                    logonProvider, out token) != 0)
                {
                    var identity = new WindowsIdentity(token);
                    var impersonationContext = identity.Impersonate();
                    if (impersonationContext != null)
                    {
                        methodToPerform.Invoke();
                        impersonationContext.Undo();
                    }
                }
                else
                {
                    // do logging
                }
            }
            if (token != IntPtr.Zero)
            {
                CloseHandle(token);
            }
        }

        #endregion Methods
    }

}